package com.flow.asyncflow.core.utils.codegeneration;


import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.flow.asyncflow.core.annotation.FlowInfo;
import com.flow.asyncflow.core.annotation.NodeInfo;
import com.flow.asyncflow.core.entity.codegeneration.VelocityModel;
import com.flow.asyncflow.core.entity.codegeneration.VelocityRequest;
import com.flow.asyncflow.core.enums.ExecuteEnum;
import com.flow.asyncflow.core.enums.NodeTypeEnum;
import com.flow.asyncflow.core.node.IFlowNode;
import com.flow.asyncflow.core.utils.beanutils.AsyncFlowBeanUtils;
import com.flow.asyncflow.core.utils.reflection.AsyncFlowReflectionUtils;
import lombok.SneakyThrows;


import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.yaml.snakeyaml.Yaml;
import org.apache.commons.lang.StringUtils;

import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
;
import java.time.LocalDateTime;
import java.util.*;

@SuppressWarnings("unchecked")
public class AsyncFlowVelocity {

    public static void buildAsyncFlowVelocity(VelocityRequest velocityRequest) throws IOException {
        String result = "";
        Yaml yaml = new Yaml();
        InputStream resourceAsStream = AsyncFlowVelocity.class.getClassLoader().getResourceAsStream("asyncflow.yml");
        Map obj = (Map) yaml.load(resourceAsStream);
        String evn = (String) obj.get("evn");
        //代码生成器仅仅在本地环境有效
        if (!evn.equals("test")) {
            return;
        }

        VelocityModel velocityModel = new VelocityModel();
        velocityModel.setReplaceManager(velocityRequest.isReplaceManager());
        //模块名称【英文描述一个单词比如合同-contract】
        velocityModel.setAsyncFlowModuleName(velocityRequest.getAsyncFlowModuleName());
        //节点描述
        velocityModel.setAsyncFlowDes(velocityRequest.getAsyncFlowModuleDes());
        //异步流责任人名称
        velocityModel.setAsyncFlowMaintainName(velocityRequest.getAsyncFlowMaintainName());
        //异步流超时报警时间(毫秒)
        velocityModel.setAsyncFlowTimeOutsLimit(velocityRequest.getAsyncFlowTimeOutsLimit());

        String AsyncFlowManagerFileName = velocityRequest.getAsyncFlowModuleName() + "Manager";//异步流管理器名称
        String AsyncFlowRequestFileName = velocityRequest.getAsyncFlowModuleName() + "Request";//异步流请求参数名称
        String AsyncFlowResponseFileName = velocityRequest.getAsyncFlowModuleName() + "Response";//异步流返回参数名称
        String AsyncFlowDataFileName = velocityRequest.getAsyncFlowModuleName() + "Context";//异步流上下文名称
        String OperatorEnumFileName = velocityRequest.getAsyncFlowModuleName() + "OperatorEnum"; //操作枚举名称
        String Author = "系统自动生成";  //文件创建人
        String Date = LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.NORM_DATETIME_PATTERN); //文件创建时间
        String AsyncFlowBaseContextName = (String) obj.get("AsyncFlowBaseContextName");//异步流【上下文基类】名称

        String sysRoot = System.getProperty("user.dir");
        // 异步流实体类（请求、返回、上下文、操作枚举）存放路径
        String AsyncFlowDomainFilePath = sysRoot + obj.get("AsyncFlowDomainFilePath");
        String AsyncFlowDomainPackagePath = (String) obj.get("AsyncFlowDomainPackagePath");
        //异步流操作类（验证、查询、操作、同步、异步、管理器等）存放路径
        String AsyncFlowExecuteFilePath = sysRoot + obj.get("AsyncFlowExecuteFilePath");
        String AsyncFlowExecutePackagePath = (String) obj.get("AsyncFlowExecutePackagePath");

        String OperatorEnumFilePath = AsyncFlowDomainFilePath + "/AsyncFlow/Enum/" + velocityModel.getAsyncFlowModuleName().toLowerCase() + "/";  //操作枚举路径
        String AsyncFlowRequestFilePath = AsyncFlowDomainFilePath + "/AsyncFlow/Model/" + velocityModel.getAsyncFlowModuleName().toLowerCase() + "/"; //异步流请求参数路径
        String AsyncFlowResponseFilePath = AsyncFlowDomainFilePath + "/AsyncFlow/Model/" + velocityModel.getAsyncFlowModuleName().toLowerCase() + "/";//异步流返回参数路径
        String AsyncFlowDataFilePath = AsyncFlowDomainFilePath + "/AsyncFlow/Context/" + velocityModel.getAsyncFlowModuleName().toLowerCase() + "/";//异步流上下文路径

        String AsyncFlowManagerFilePath = AsyncFlowExecuteFilePath + "/Manager/" + velocityModel.getAsyncFlowModuleName().toLowerCase() + "/"; //异步流管理器路径
        String AsyncFlowValidatorFilePath = AsyncFlowExecuteFilePath + "/Validator/" + velocityModel.getAsyncFlowModuleName().toLowerCase() + "/"; //异步流管理器路径
        String AsyncFlowPubGetDataFilePath = AsyncFlowExecuteFilePath + "/GetData/pubgetdata/"; //异步流管理器路径
        String AsyncFlowGetDataFilePath = AsyncFlowExecuteFilePath + "/GetData/" + velocityModel.getAsyncFlowModuleName().toLowerCase() + "/"; //异步流管理器路径
        String AsyncFlowOperatorFilePath = AsyncFlowExecuteFilePath + "/Operator/" + velocityModel.getAsyncFlowModuleName().toLowerCase() + "/"; //异步流管理器路径
        String AsyncFlowSyncFilePath = AsyncFlowExecuteFilePath + "/Sync/" + velocityModel.getAsyncFlowModuleName().toLowerCase() + "/"; //异步流管理器路径
        String AsyncFlowAsyncFilePath = AsyncFlowExecuteFilePath + "/Async/" + velocityModel.getAsyncFlowModuleName().toLowerCase() + "/"; //异步流管理器路径


        String OperatorEnumPackagePath = AsyncFlowDomainPackagePath + ".AsyncFlow.Enum." + velocityModel.getAsyncFlowModuleName().toLowerCase();  //操作枚举路径
        String AsyncFlowRequestPackagePath = AsyncFlowDomainPackagePath + ".AsyncFlow.Model." + velocityModel.getAsyncFlowModuleName().toLowerCase(); //异步流请求参数路径
        String AsyncFlowResponsePackagePath = AsyncFlowDomainPackagePath + ".AsyncFlow.Model." + velocityModel.getAsyncFlowModuleName().toLowerCase();//异步流返回参数路径
        String AsyncFlowDataPackagePath = AsyncFlowDomainPackagePath + ".AsyncFlow.Context." + velocityModel.getAsyncFlowModuleName().toLowerCase();//异步流上下文路径
        String AsyncFlowBaseContextPackagePath = AsyncFlowDomainPackagePath + ".AsyncFlow.Context";//异步流上下文路径【上下文基类】

        String AsyncFlowManagerPackagePath = AsyncFlowExecutePackagePath + ".Manager." + velocityModel.getAsyncFlowModuleName().toLowerCase(); //异步流管理器路径
        String AsyncFlowValidatorPackagePath = AsyncFlowExecutePackagePath + ".Validator." + velocityModel.getAsyncFlowModuleName().toLowerCase(); //异步流管理器路径
        String AsyncFlowPubGetDataPackagePath = AsyncFlowExecutePackagePath + ".GetData.pubgetdata"; //异步流公共查询包路径
        String AsyncFlowGetDataPackagePath = AsyncFlowExecutePackagePath + ".GetData." + velocityModel.getAsyncFlowModuleName().toLowerCase(); //异步流管理器路径
        String AsyncFlowOperatorPackagePath = AsyncFlowExecutePackagePath + ".Operator." + velocityModel.getAsyncFlowModuleName().toLowerCase(); //异步流管理器路径
        String AsyncFlowSyncPackagePath = AsyncFlowExecutePackagePath + ".Sync." + velocityModel.getAsyncFlowModuleName().toLowerCase(); //异步流管理器路径
        String AsyncFlowAsyncPackageFilePath = AsyncFlowExecutePackagePath + ".Async." + velocityModel.getAsyncFlowModuleName().toLowerCase(); //异步流管理器路径


        //异步流操作枚举相关信息
        velocityModel.setOperatorEnumFileName(OperatorEnumFileName);
        velocityModel.setOperatorEnumFilePath(OperatorEnumFilePath);
        velocityModel.setOperatorEnumPackagePath(OperatorEnumPackagePath);
        //异步流请求参数相关信息
        velocityModel.setAsyncFlowRequestFileName(AsyncFlowRequestFileName);
        velocityModel.setAsyncFlowRequestFilePath(AsyncFlowRequestFilePath);
        velocityModel.setAsyncFlowRequestPackagePath(AsyncFlowRequestPackagePath);
        //异步流返回参数相关信息
        velocityModel.setAsyncFlowResponseFileName(AsyncFlowResponseFileName);
        velocityModel.setAsyncFlowResponseFilePath(AsyncFlowResponseFilePath);
        velocityModel.setAsyncFlowResponsePackagePath(AsyncFlowResponsePackagePath);
        //异步流上下文基类相关信息
        if (velocityRequest.isHasBaseContext()) {
            velocityModel.setHasBaseContext(true);
            velocityModel.setBaseContextFileName(AsyncFlowBaseContextName);
            velocityModel.setBaseContextPackagePath(AsyncFlowBaseContextPackagePath);
        } else {
            velocityModel.setHasBaseContext(false);
            velocityModel.setBaseContextFileName("");
            velocityModel.setBaseContextFilePath("");
            velocityModel.setBaseContextPackagePath("");
        }
        //异步流上下文相关信息
        velocityModel.setAsyncFlowDataFileName(AsyncFlowDataFileName);
        velocityModel.setAsyncFlowDataFilePath(AsyncFlowDataFilePath);
        velocityModel.setAsyncFlowDataPackagePath(AsyncFlowDataPackagePath);

        //异步流节点相关信息
        velocityModel.getAsyncFlowNodeInfoList().addAll(velocityRequest.getAsyncFlowNodeInfoList());
        //异步流管理器相关信息
        velocityModel.setAsyncFlowManagerFileName(AsyncFlowManagerFileName);
        velocityModel.setAsyncFlowManagerFilePath(AsyncFlowManagerFilePath);
        velocityModel.setAsyncFlowManagerPackagePath(AsyncFlowManagerPackagePath);

        //老的并且需要覆盖的时候则用请求过来的原来的文件路径和包路径
        Object oldManager = AsyncFlowBeanUtils.getBean(lowerFirst(velocityModel.getAsyncFlowManagerFileName()));
        if (oldManager != null) {
            velocityModel.setNewManager(false);
            if (!velocityModel.isNewManager() && velocityRequest.isReplaceManager()) {

                Class oldOperatorEnumClazz = null;
                ParameterizedType parameterizedType = (ParameterizedType) oldManager.getClass().getGenericSuperclass();
                Type reqEnumClazz = null;
                if (parameterizedType.getActualTypeArguments().length == 2) {
                    reqEnumClazz = parameterizedType.getActualTypeArguments()[1];
                    oldOperatorEnumClazz = (Class<Enum>) reqEnumClazz;
                }
                Class oldRequestClazz = getClass(AsyncFlowDomainPackagePath + ".AsyncFlow.Model", velocityModel.getAsyncFlowRequestFileName());
                Class oldResponseClazz = getClass(AsyncFlowDomainPackagePath + ".AsyncFlow.Model", velocityModel.getAsyncFlowResponseFileName());
                Class oldContextClazz = getClass(AsyncFlowDomainPackagePath + ".AsyncFlow.Context", velocityModel.getAsyncFlowDataFileName());

                String oldAsyncFlowManagerFilePath;
                oldAsyncFlowManagerFilePath = oldManager.getClass().getResource("").getPath().replace("target/classes", "src/main/java");
                velocityModel.setAsyncFlowManagerFilePath(oldAsyncFlowManagerFilePath);
                velocityModel.setAsyncFlowManagerPackagePath(oldManager.getClass().getPackage().getName());
                velocityModel.setOperatorEnumPackagePath(oldOperatorEnumClazz.getPackage().getName());
                velocityModel.setAsyncFlowRequestPackagePath(oldRequestClazz.getPackage().getName());
                velocityModel.setAsyncFlowResponsePackagePath(oldResponseClazz.getPackage().getName());
                velocityModel.setAsyncFlowDataPackagePath(oldContextClazz.getPackage().getName());

            }
        }

        velocityModel.getAsyncFlowOperatorEnumInfoList().addAll(velocityRequest.getAsyncFlowOperatorEnumInfoList());
        if (velocityModel.getAsyncFlowOperatorEnumInfoList().isEmpty() || velocityModel.getAsyncFlowOperatorEnumInfoList().stream().noneMatch(c -> c.getName().equals("Defaults"))) {
            VelocityModel.AsyncFlowOperatorEnumInfo addAsyncFlowOperatorEnumInfo = null;
            addAsyncFlowOperatorEnumInfo = new VelocityModel.AsyncFlowOperatorEnumInfo();
            //没有添加默认枚举，并且也没有其他枚举时，新增的默认枚举是默认选中的
            if (velocityModel.getAsyncFlowOperatorEnumInfoList().isEmpty()) {
                addAsyncFlowOperatorEnumInfo.setNewEnumValue(true);
            }

            addAsyncFlowOperatorEnumInfo.setMsg("默认");
            addAsyncFlowOperatorEnumInfo.setCode(0);
            addAsyncFlowOperatorEnumInfo.setName("Defaults");
            velocityModel.getAsyncFlowOperatorEnumInfoList().addFirst(addAsyncFlowOperatorEnumInfo);
        }
        boolean hasNewOperatorEnum = false;
        VelocityModel.AsyncFlowOperatorEnumInfo asyncFlowOperatorEnumInfo = velocityRequest.getAsyncFlowOperatorEnumInfoList().stream().filter(VelocityModel.AsyncFlowOperatorEnumInfo::isSelect).findFirst().orElse(null);
        if (asyncFlowOperatorEnumInfo == null) {
            asyncFlowOperatorEnumInfo = velocityRequest.getAsyncFlowOperatorEnumInfoList().stream().filter(c -> c.getName().equals("Defaults")).findFirst().orElse(null);

        } else {
            hasNewOperatorEnum = true;
            velocityModel.setReplaceOperatorEnum(true);
        }
        velocityModel.setAsyncFlowOperatorEnumInfo(asyncFlowOperatorEnumInfo);

        //异步流类文件创建者相关信息
        velocityModel.setAuthor(Author);
        velocityModel.setDate(Date);

        //当前Manager是新建的或者存在新增的枚举需要操作枚举
        if (velocityModel.isNewManager() || hasNewOperatorEnum) {
            //生成操作枚举
            if (StringUtils.isNotBlank(velocityModel.getOperatorEnumFileName()) && StringUtils.isNotBlank(velocityModel.getOperatorEnumFilePath())) {
                buildSubAsyncFlowVelocity(velocityModel, velocityModel.getOperatorEnumFileName(), velocityModel.getOperatorEnumFilePath(), "OperatorEnumVelocity");
            }

        }
        //当前Manager是新建的才需要生成请求、返回参数，操作枚举、上下文
        if (velocityModel.isNewManager()) {

            //生成请求参数
            if (StringUtils.isNotBlank(velocityModel.getAsyncFlowRequestFileName()) && StringUtils.isNotBlank(velocityModel.getAsyncFlowRequestFilePath())) {
                buildSubAsyncFlowVelocity(velocityModel, velocityModel.getAsyncFlowRequestFileName(), velocityModel.getAsyncFlowRequestFilePath(), "RequestVelocity");
            }
            //生成返回参数
            if (StringUtils.isNotBlank(velocityModel.getAsyncFlowResponseFileName()) && StringUtils.isNotBlank(velocityModel.getAsyncFlowResponseFilePath())) {
                buildSubAsyncFlowVelocity(velocityModel, velocityModel.getAsyncFlowResponseFileName(), velocityModel.getAsyncFlowResponseFilePath(), "ResponseVelocity");
            }
            //生成上下文
            if (StringUtils.isNotBlank(velocityModel.getAsyncFlowDataFileName()) && StringUtils.isNotBlank(velocityModel.getAsyncFlowDataFilePath())) {

                buildSubAsyncFlowVelocity(velocityModel, velocityModel.getAsyncFlowDataFileName(), velocityModel.getAsyncFlowDataFilePath(), "ContextVelocity");
            }
        }


        //生成操作节点
        if (!velocityRequest.getAsyncFlowNodeInfoList().isEmpty()) {
            for (VelocityModel.AsyncFlowNodeInfo asyncFlowNodeInfo : velocityModel.getAsyncFlowNodeInfoList()) {
                //已经生成好的公共操作节点，不需要生成文件，只要在manager里面生成对应的引用即可
                if (asyncFlowNodeInfo.getNodeTypeEnum() == NodeTypeEnum.OldPubNode || asyncFlowNodeInfo.getNodeTypeEnum() == NodeTypeEnum.OldSpecialNode) {
                    continue;
                }


                Class oldExecuteNodeClazz;
                switch (asyncFlowNodeInfo.getExecuteEnum().getName()) {
                    case "Validator":
                        asyncFlowNodeInfo.setAsyncFlowNodeFilePath(AsyncFlowValidatorFilePath);
                        asyncFlowNodeInfo.setAsyncFlowNodePackagePath(AsyncFlowValidatorPackagePath);
                        break;
                    case "GetDataPub":
                        asyncFlowNodeInfo.setAsyncFlowNodeFilePath(AsyncFlowPubGetDataFilePath);
                        asyncFlowNodeInfo.setAsyncFlowNodePackagePath(AsyncFlowPubGetDataPackagePath);
                        asyncFlowNodeInfo.setNodeTypeEnum(NodeTypeEnum.NewPubNode);
                        break;
                    case "GetData":
                        asyncFlowNodeInfo.setAsyncFlowNodeFilePath(AsyncFlowGetDataFilePath);
                        asyncFlowNodeInfo.setAsyncFlowNodePackagePath(AsyncFlowGetDataPackagePath);
                        break;
                    case "Operator":
                        asyncFlowNodeInfo.setAsyncFlowNodeFilePath(AsyncFlowOperatorFilePath);
                        asyncFlowNodeInfo.setAsyncFlowNodePackagePath(AsyncFlowOperatorPackagePath);
                        break;
                    case "Sync":
                        asyncFlowNodeInfo.setAsyncFlowNodeFilePath(AsyncFlowSyncFilePath);
                        asyncFlowNodeInfo.setAsyncFlowNodePackagePath(AsyncFlowSyncPackagePath);
                        break;
                    case "Async":
                        asyncFlowNodeInfo.setAsyncFlowNodeFilePath(AsyncFlowAsyncFilePath);
                        asyncFlowNodeInfo.setAsyncFlowNodePackagePath(AsyncFlowAsyncPackageFilePath);
                        asyncFlowNodeInfo.setAsync(true);
                        break;
                }
                //如果是历史已经存在的Manager
                if (!velocityModel.isNewManager()) {
                    //找到已经生成的manager中相同的操作节点的 包路径和文件路径，生成到相同的地方去
                    VelocityModel.AsyncFlowNodeInfo oldNode = velocityModel.getAsyncFlowNodeInfoList().stream().filter(c -> c.getExecuteEnum().equals(asyncFlowNodeInfo.getExecuteEnum()) && (c.getNodeTypeEnum() == NodeTypeEnum.OldPubNode || c.getNodeTypeEnum() == NodeTypeEnum.OldSpecialNode)).findFirst().orElse(null);
                    if (oldNode != null) {
                        oldExecuteNodeClazz = getClass(oldNode.getAsyncFlowNodePackagePath(), oldNode.getAsyncFlowNodeFileName());
                        asyncFlowNodeInfo.setAsyncFlowNodeFilePath(oldExecuteNodeClazz.getResource("").getPath().replace("target/classes", "src/main/java"));
                        asyncFlowNodeInfo.setAsyncFlowNodePackagePath(oldExecuteNodeClazz.getPackage().getName());
                    }

                }
                if (StringUtils.isNotBlank(asyncFlowNodeInfo.getAsyncFlowNodeFileName()) && StringUtils.isNotBlank(asyncFlowNodeInfo.getAsyncFlowNodeFilePath())) {
                    velocityModel.setAsyncFlowNodeInfo(asyncFlowNodeInfo);
                    buildSubAsyncFlowVelocity(velocityModel, asyncFlowNodeInfo.getAsyncFlowNodeFileName(), asyncFlowNodeInfo.getAsyncFlowNodeFilePath(), "ExecuteVelocity");
                }
            }
        }
        //只有是新的Manager或者是老的并且需要覆盖原来的Manager时才需要重新生成
        if (velocityModel.isNewManager() || (!velocityModel.isNewManager() && velocityRequest.isReplaceManager())) {


            //生成管理器
            if (StringUtils.isNotBlank(velocityModel.getAsyncFlowManagerFileName()) && StringUtils.isNotBlank(velocityModel.getAsyncFlowManagerFilePath())) {
                buildSubAsyncFlowVelocity(velocityModel, velocityModel.getAsyncFlowManagerFileName(), velocityModel.getAsyncFlowManagerFilePath(), "ManagerVelocity");
            }
        }


    }


    private static void buildSubAsyncFlowVelocity(VelocityModel velocityModel, String fileName, String filePath, String templateName) throws IOException {
        // 初始化模板引擎
        VelocityEngine ve = new VelocityEngine();
        ve.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, Class.class.getResource("/").getPath() + "templates/velocity");
        ve.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
        ve.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
        ve.init();
        // 获取模板文件
        Template template = ve.getTemplate(templateName + ".vm");
        // 设置变量
        VelocityContext ctx = new VelocityContext();
        ctx.put("model", velocityModel);

        filePath = filePath + fileName + ".java";//输出文件的地址

        boolean replaceFile = false;
        if (templateName.equals("ManagerVelocity")) {
            replaceFile = velocityModel.isReplaceManager();
        }
        if (templateName.equals("OperatorEnumVelocity")) {
            replaceFile = velocityModel.isReplaceOperatorEnum();
        }
        File file = new File(filePath);
        if (!file.exists()) {
            file.getParentFile().mkdirs();
        } else {
            //文件存在，如果传参指定需要覆盖，则不跳出，重新生成进行覆盖，否则 跳出，不进行生成
            //不覆盖
            if (!replaceFile) {
                //文件存在不做覆盖
                return;
            }

        }
        FileOutputStream fos = new FileOutputStream(filePath);
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, StandardCharsets.UTF_8));
        template.merge(ctx, writer);
        writer.close();


    }


    /**
     * 根据包路径加载公共Node
     *
     * @param packagePath 路径
     * @return NodeAndManager集合
     */
    public static LinkedList<VelocityModel.AsyncFlowNodeInfo> loadNodeAndManagerV2(String packagePath) {
        LinkedList<VelocityModel.AsyncFlowNodeInfo> oldAsyncFlowNodeInfoList = new LinkedList<>();

        //Validator：验证   GetData：查询    GetDataPub：公共查询  Operator：操作   Save：保存    Sync：保存后同步    Async：保存后异步

        Set<Class<?>> classes;
        classes = AsyncFlowReflectionUtils.getClasses(packagePath);
        for (Class c : classes) {
            VelocityModel.AsyncFlowNodeInfo asyncFlowNodeInfo = new VelocityModel.AsyncFlowNodeInfo();

            ExecuteEnum executeEnum = null;

            if (StrUtil.endWith(c.getSimpleName(), ExecuteEnum.Validator.name())
                    || c.getName().contains(".Validator.")) {
                executeEnum = ExecuteEnum.Validator;

            } else if (StrUtil.endWith(c.getSimpleName(), ExecuteEnum.GetData.name())
                    || c.getName().contains(".GetData.")) {
                executeEnum = ExecuteEnum.GetData;
            } else if (StrUtil.endWith(c.getSimpleName(), ExecuteEnum.GetDataPub.name())
                    || c.getName().contains(".GetData.")) {
                executeEnum = ExecuteEnum.GetDataPub;
            } else if (StrUtil.endWith(c.getSimpleName(), ExecuteEnum.Operator.name())
                    || c.getName().contains(".Operator.")) {
                executeEnum = ExecuteEnum.Operator;
            } else if (StrUtil.endWith(c.getSimpleName(), ExecuteEnum.Save.name())
                    || c.getName().contains(".Save.")) {
                executeEnum = ExecuteEnum.Save;
            } else if (StrUtil.endWith(c.getSimpleName(), ExecuteEnum.Sync.name())
                    || c.getName().contains(".Sync.")) {
                executeEnum = ExecuteEnum.Sync;
            } else if (StrUtil.endWith(c.getSimpleName(), ExecuteEnum.Async.name())
                    || c.getName().contains(".Async.")) {
                executeEnum = ExecuteEnum.Async;
            } else if (StrUtil.endWith(c.getSimpleName(), ExecuteEnum.Manager.name())
                    || c.getName().contains(".Manager.")) {
                executeEnum = ExecuteEnum.Manager;
            }

            Annotation[] methodInfos = c.getAnnotations();
            for (Annotation annotation : methodInfos) {
                //获取方法名
                if (annotation instanceof FlowInfo) {
                    asyncFlowNodeInfo.setAsyncFlowNodeDes(((FlowInfo) annotation).flowName());
                    asyncFlowNodeInfo.setNodeTypeEnum(NodeTypeEnum.OldSpecialNode);
                    executeEnum = ExecuteEnum.Manager;
                    break;
                }
                //获取方法名
                if (annotation instanceof NodeInfo) {
                    asyncFlowNodeInfo.setAsyncFlowNodeDes(((NodeInfo) annotation).name());
                    asyncFlowNodeInfo.setNodeTypeEnum(((NodeInfo) annotation).nodeType());
                    break;
                }


            }
            //默认是操作节点
            if (executeEnum == null) {
                executeEnum = ExecuteEnum.Operator;
            }
            //对于不是Manager 的节点，如果不是公共节点直接跳出，不需要加载
            if (executeEnum != ExecuteEnum.Manager
                    && asyncFlowNodeInfo.getNodeTypeEnum() != NodeTypeEnum.NewPubNode
                    && asyncFlowNodeInfo.getNodeTypeEnum() != NodeTypeEnum.OldPubNode) {
                continue;
            }
            asyncFlowNodeInfo.setExecuteEnum(executeEnum);
            asyncFlowNodeInfo.setAsyncFlowNodeFileName(c.getSimpleName());
            asyncFlowNodeInfo.setAsyncFlowNodePackagePath(c.getPackage().getName());
            //公共查询或者异步操作全部都是异步执行
            if (executeEnum == ExecuteEnum.GetDataPub || executeEnum == ExecuteEnum.Async) {
                asyncFlowNodeInfo.setAsync(true);
            }


            oldAsyncFlowNodeInfoList.add(asyncFlowNodeInfo);
        }
        return oldAsyncFlowNodeInfoList;
    }

    /**
     * 根据包路径和Manager名称加载原有异步流的所有节点
     *
     * @param managerName 元异步流名称
     * @param packagePath 路径
     * @return 原异步流所有Node集合
     */
    @SneakyThrows
    public static VelocityRequest loadManagerNode(String managerName, String packagePath) {
        VelocityRequest velocityModel = new VelocityRequest();
        //Validator：验证   GetData：查询    GetDataPub：公共查询  Operator：操作   Save：保存    Sync：保存后同步    Async：保存后异步
        Class clazz;
        clazz = getClass(packagePath, managerName);
        if (clazz == null) {
            return velocityModel;
        }
        ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass();
        Type reqEnumClazz = null;
        if (parameterizedType.getActualTypeArguments().length == 2) {
            reqEnumClazz = parameterizedType.getActualTypeArguments()[1];
        }

        velocityModel.setAsyncFlowModuleName(managerName.replace("Manager", ""));
        velocityModel.getAsyncFlowOperatorEnumInfoList().addAll(getEnumInfo(reqEnumClazz));
        //velocityModel.
        Annotation[] flowNodeInfo = clazz.getAnnotations();
        for (Annotation annotation : flowNodeInfo) {
            //获取方法名
            if (annotation instanceof FlowInfo) {
                velocityModel.setAsyncFlowModuleDes(((FlowInfo) annotation).flowName());
                velocityModel.setAsyncFlowMaintainName(((FlowInfo) annotation).flowMaintainName());
                velocityModel.setAsyncFlowTimeOutsLimit(((FlowInfo) annotation).timeOutsLimit());
                break;
            }
        }
        Class clazzFather = clazz.getSuperclass();
        Object manager = AsyncFlowBeanUtils.getBean(clazz);
        Method m = clazz.getDeclaredMethod("managerStartup");
        m.setAccessible(true);
        m.invoke(manager);
        Field field = clazzFather.getDeclaredField("flowNodes");
        //设置对象的访问权限，保证对private的属性的访问
        field.setAccessible(true);
        //原始版AsyncFLow
        LinkedHashMap<ExecuteEnum, LinkedHashMap<IFlowNode, Boolean>> s = (LinkedHashMap<ExecuteEnum, LinkedHashMap<IFlowNode, Boolean>>) field.get(manager);
        for (Map.Entry<ExecuteEnum, LinkedHashMap<IFlowNode, Boolean>> entry : s.entrySet()) {
            for (Map.Entry<IFlowNode, Boolean> subEntry : entry.getValue().entrySet()) {
                VelocityModel.AsyncFlowNodeInfo asyncFlowNodeInfo = new VelocityModel.AsyncFlowNodeInfo();
                Class c = subEntry.getKey().getClass();

                asyncFlowNodeInfo.setExecuteEnum(ExecuteEnum.getEnum(entry.getKey().getName()));
                if (entry.getKey().getName().equals("GetDataPub")) {
                    asyncFlowNodeInfo.setNodeTypeEnum(NodeTypeEnum.OldPubNode);
                } else {
                    asyncFlowNodeInfo.setNodeTypeEnum(NodeTypeEnum.OldSpecialNode);
                }
                asyncFlowNodeInfo.setAsyncFlowNodeFileName(c.getSimpleName());
                asyncFlowNodeInfo.setAsync(subEntry.getValue());
                asyncFlowNodeInfo.setAsyncFlowNodePackagePath(c.getPackage().getName());
                //asyncFlowNodeInfo.setAsyncFlowNodeFilePath();
                Annotation[] subLogMethods = c.getAnnotations();
                for (Annotation annotation : subLogMethods) {
                    //获取方法名
                    if (annotation instanceof NodeInfo) {
                        asyncFlowNodeInfo.setAsyncFlowNodeDes(((NodeInfo) annotation).name());
                        break;
                    }
                }

                velocityModel.getAsyncFlowNodeInfoList().add(asyncFlowNodeInfo);
            }
        }

        return velocityModel;
    }


    private static String lowerFirst(String str) {
        String firstStr = str.substring(0, 1);
        String endStr = str.substring(1);
        return firstStr.toLowerCase() + endStr;
    }

    /**
     * 根据包路径获取 和枚举名称获取枚举集合
     *
     * @param packagePath 路径
     * @param className   名称
     * @return 类
     */
    private static Class getClass(String packagePath, String className) {
        Set<Class<?>> oldClasses;
        Class clazz = null;
        oldClasses = AsyncFlowReflectionUtils.getClasses(packagePath);
        for (Class c : oldClasses) {
            if (c.getSimpleName().equals(className)) {
                clazz = c;
                break;
            }
        }
        return clazz;
    }

    /**
     * 根据枚举的字符串获取枚举的值
     *
     * @param reqEnumType 操作枚举
     * @return 枚举集合
     */
    public static LinkedList<VelocityModel.AsyncFlowOperatorEnumInfo> getEnumInfo(Type reqEnumType) throws Exception {
        LinkedList<VelocityModel.AsyncFlowOperatorEnumInfo> asyncFlowOperatorEnumInfoLinkedList = new LinkedList<>();
        Yaml yaml = new Yaml();
        InputStream resourceAsStream = AsyncFlowVelocity.class.getClassLoader().getResourceAsStream("asyncflow.yml");
        Map obj = yaml.load(resourceAsStream);
        String AsyncFlowDomainPackagePath = (String) obj.get("AsyncFlowDomainPackagePath");
        String operatorPackagePath = AsyncFlowDomainPackagePath + ".AsyncFlow.Enum";
        // 得到枚举类对象
        Class<Enum> clazz = (Class<Enum>) reqEnumType;
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        if (clazz == null) {
            return asyncFlowOperatorEnumInfoLinkedList;
        }
        //获取所有枚举实例
        Enum[] enumConstants = clazz.getEnumConstants();
        //根据方法名获取方法
        Method getCode = clazz.getMethod("getCode");
        Method getMessage = clazz.getMethod("getMsg");
        Map<String, Object> map = null;
        for (Enum enum1 : enumConstants) {
            VelocityModel.AsyncFlowOperatorEnumInfo asyncFlowOperatorEnumInfo = new VelocityModel.AsyncFlowOperatorEnumInfo();
            //map = new HashMap<String, Object>();
            //map.put("name",enum1.name());
            ////执行枚举方法获得枚举实例对应的值
            //map.put("code", getCode.invoke(enum1));
            //map.put("msg", getMessage.invoke(enum1));
            asyncFlowOperatorEnumInfo.setName(enum1.name());
            asyncFlowOperatorEnumInfo.setCode(getCode.invoke(enum1));
            asyncFlowOperatorEnumInfo.setMsg(getMessage.invoke(enum1));
            asyncFlowOperatorEnumInfo.setNewEnumValue(false);
            asyncFlowOperatorEnumInfo.setSelect(false);
            asyncFlowOperatorEnumInfoLinkedList.add(asyncFlowOperatorEnumInfo);
        }
        return asyncFlowOperatorEnumInfoLinkedList;
    }
}




